package pCloud.transport;

import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.HashMap;

import org.apache.log4j.Logger;

import pCloud.message.ClientResponse;
import pCloud.message.Message;
import pCloud.service.ProtocolHandle;

/**
 * This singleton provides access to all the communication channels
 * 
 * Each client, server has this object that keeps track of exisitng connections,
 * both outgoing and incoming. This is important because the proxy, for example,
 * receives messages from one socket and forwards it to another.
 * 
 * All the connections are identified by the InetAddress.
 * 
 * The communicator also mapping of dataID to the database address. It makes sense for 
 * both proxy and cloud server to maintain such mapping. 
 */
public class SocketCommunicator implements Communicator {
	public HashMap<InetSocketAddress, ProtocolHandle> connections;
	HashMap<String, DatabaseAddress> dataIdMap;
	
	boolean isInitialized = false;
	public Logger logger;

	@Override
	public void init(Logger l) {
		connections = new HashMap<InetSocketAddress, ProtocolHandle>();
		dataIdMap = new HashMap<String, DatabaseAddress>();
		isInitialized = true;
		logger = l;
	}

	@Override
	public Logger getLogger() {
		return this.logger;
	}

	@Override
	public void addConnection(ProtocolHandle ph) throws Exception {
		InetSocketAddress isa = (InetSocketAddress) ph.getTransportHanlde()
				.getRemoteAddress();
		//System.out.println(this.toString()+" adding connection "+isa+" using protocol handle "+ph);
		if (connections.containsKey(isa))
			System.err.println("Connection " + isa + " already existed");
		connections.put(isa, ph);
		logger.debug("Connection " + isa + " added");
	}

	@Override
	public void removeConnection(ProtocolHandle ph) throws Exception {
		InetSocketAddress isa = (InetSocketAddress) ph.getTransportHanlde()
				.getRemoteAddress();
		connections.remove(isa);
		logger.debug("Connection " + isa + " removed");
	}

	@Override
	public TransportHandle getConnection(Object id) throws Exception {
		Object[] others = connections.keySet().toArray();
		
		if (connections.get(id) == null){
			System.out.println("Connection " + id + " does not exist here "+this.toString());
		}
		return connections.get(id).getTransportHanlde();
	}

	@Override
	public void send(Object id, Message msg) throws Exception {
		this.getConnection(id).send(msg);
		logger.debug("Message  sent to " + id + " with content of type "
				+ msg.getMessageContent().getClass().getName());
	}

	@Override
	public HashMap<String, DatabaseAddress> getDataIdMap() {
		return this.dataIdMap;
	}

	@Override
	public void addToDataIdMap(String key, DatabaseAddress da) {		
		this.dataIdMap.put(key, da);
	}
}
